package com.gzsxy.esjy.message.netty.handler;


import com.gzsxy.esjy.message.channel.ChannelManager;
import com.gzsxy.esjy.message.dispatch.MessageDispatch;
import com.gzsxy.esjy.message.netty.Message;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.util.function.Function;

/**
 *  1. SimpleChannelInboundHandler 是 ChannelInboundHandlerAdapter父类
 *   handler处理器
 */
@Slf4j
public class InnerPortolHandler extends SimpleChannelInboundHandler<Message> {

    private final static String HEARTBEAT = "/heartbeat";

    private final MessageDispatch messageDispatch;

    private Function<String, Object> heartBeat = (str) -> new PingWebSocketFrame();

    public InnerPortolHandler(MessageDispatch messageDispatch) {
        super();
        this.messageDispatch = messageDispatch;
    }

    /**
     * 通道读取数据事件
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
        String cmd = msg.getCmd();
        if (cmd.equalsIgnoreCase(HEARTBEAT)) {
            log.debug("接收到来自于 {} 的心跳信息 ", ctx.channel().attr(ChannelManager.IP).get());
            ctx.channel().writeAndFlush(new TextWebSocketFrame());
            return;
        }
        //处理其他
        messageDispatch.webSocketToBus(ctx.channel(), msg);
    }

    /**
     * 通道就绪事件
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        messageDispatch.channelCloseEvent(ctx.channel());
        log.info("通道{} 创建", ctx.channel().toString());
    }

    /**
     * 断开链接
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("通道{} 销毁", ctx.channel().attr(ChannelManager.IP).get());
        ctx.close();
    }

    /**
     * 异常事件
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error(cause.getMessage(), cause);
        ctx.close();
    }

    /**
     * 事件监听
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //心跳事件
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                //写空闲
                case WRITER_IDLE:
                    //发送写心跳
                    ctx.channel().writeAndFlush(this.heartBeat.apply(""));
                    log.info("向通道 {}发送 心跳",ctx.channel().attr(ChannelManager.IP).get());
                    break;
                default:
                    log.info("通到 {} 长时间 未收到信息 ,自动关闭", ctx.channel().attr(ChannelManager.IP).get());
                    ctx.close();
                    break;
            }
        }
    }

    public void setHeartBeat(Function<String, Object> heartBeat) {
        this.heartBeat = heartBeat;
    }
}
